const wrapper = document.getElementById("signature-pad")
 const clearButton = wrapper.querySelector("[data-action=clear]")
 const changeColorButton = wrapper.querySelector("[data-action=change-color]")
 const undoButton = wrapper.querySelector("[data-action=undo]")
 const savePNGButton = wrapper.querySelector("[data-action=save-png]")
 const saveJPGButton = wrapper.querySelector("[data-action=save-jpg]")
 const saveSVGButton = wrapper.querySelector("[data-action=save-svg]")
 const canvas = wrapper.querySelector("canvas")
 const fileSelector = document.getElementById('fileupload')

// https://medium.com/the-everyday-developer/detect-file-mime-type-using-magic-numbers-and-javascript-16bc513d4e1e
const verifyAndSetPictureAsBackground = (event) => {
  const file = event.target.files[0]
  const fReader = new FileReader()
  fReader.onloadend = (e) => {
    if (e.target.readyState === FileReader.DONE) {
      const uint = new Uint8Array(e.target.result)
      let bytes = []
      uint.forEach((byte) => bytes.push(byte.toString(16)))
      const hex = bytes.join('').toUpperCase()
      if (!(getMimeType(hex) === 'image/png' || getMimeType(hex) === 'image/gif' || getMimeType(hex) === 'image/jpeg')) {
        alert('Please choose a picture(.png, .gif, or .jpeg)')
        // https://stackoverflow.com/a/35323290/1904223
        file = null
        fileSelector.value = ''
        if (!/safari/i.test(navigator.userAgent)) {
          fileSelector.type = ''
          fileSelector.type = 'file'
        }
      }
      if (file) {
        const dataURL = window.URL.createObjectURL(file)
        signaturePad.fromDataURL(dataURL)
      }
    }
  }
  fReader.readAsArrayBuffer(file.slice(0, 4))
}

const getMimeType = (signature) => {
  switch (signature) {
    case '89504E47':
      return 'image/png'
    case '47494638':
      return 'image/gif'
    case 'FFD8FFDB':
    case 'FFD8FFE0':
    case 'FFD8FFE1':
      return 'image/jpeg'
    default:
      return 'Not allowed filetype'
  }
}

fileSelector.addEventListener('change', verifyAndSetPictureAsBackground, false)

const signaturePad = new SignaturePad(canvas, {
  // It's Necessary to use an opaque color when saving image as JPEG
  // this option can be omitted if only saving as PNG or SVG
  backgroundColor: 'rgb(255, 255, 255)'
})

// Adjust canvas coordinate space taking into account pixel ratio,
// to make it look crisp on mobile devices.
// This also causes canvas to be cleared.
const resizeCanvas = () => {
  // When zoomed out to less than 100%, for some very strange reason,
  // some browsers report devicePixelRatio as less than 1
  // and only part of the canvas is cleared then.
   const ratio =  Math.max(window.devicePixelRatio || 1, 1)

  // This part causes the canvas to be cleared
  canvas.width = canvas.offsetWidth * ratio
  canvas.height = canvas.offsetHeight * ratio
  canvas.getContext("2d").scale(ratio, ratio)

  // This library does not listen for canvas changes, so after the canvas is automatically
  // cleared by the browser, SignaturePad#isEmpty might still return false, even though the
  // canvas looks empty, because the internal data of this library wasn't cleared. To make sure
  // that the state of this library is consistent with visual state of the canvas, you
  // have to clear it manually.
  signaturePad.clear()
}

// On mobile devices it might make more sense to listen to orientation change,
// rather than window resize events.
window.onresize = resizeCanvas
resizeCanvas()

const download = (dataURL, filename) => {
  const blob = dataURLToBlob(dataURL)
  const url = window.URL.createObjectURL(blob)

  const a = document.createElement("a")
  a.style = "display: none"
  a.href = url
  a.download = filename

  document.body.appendChild(a)
  a.click()

  window.URL.revokeObjectURL(url)
}

// One could simply use Canvas#toBlob method instead, but it's just to show
// that it can be done using result of SignaturePad#toDataURL.
function dataURLToBlob(dataURL) {
  // Code taken from https://github.com/ebidel/filer.js
   const parts = dataURL.split('base64,')
   const contentType = parts[0].split(":")[1]
   const raw = window.atob(parts[1])
   const rawLength = raw.length
   const uInt8Array = new Uint8Array(rawLength)

  for (let i = 0;  i < rawLength;  ++i) {
    uInt8Array[i] = raw.charCodeAt(i)
  }

  return new Blob([uInt8Array], { type: contentType })
}

clearButton.addEventListener("click", () => signaturePad.clear())

undoButton.addEventListener("click", () => {
  const data = signaturePad.toData()

  if (data) {
    data.pop()  // remove the last dot or line
    signaturePad.fromData(data)
  }
})

changeColorButton.addEventListener("click", () => {
  const r = Math.round(Math.random() * 255)
  const g = Math.round(Math.random() * 255)
  const b = Math.round(Math.random() * 255)
  const color = "rgb(" + r + "," + g + "," + b +")"

  signaturePad.penColor = color
})

savePNGButton.addEventListener("click", () => {
  if (signaturePad.isEmpty()) {
    alert("Please provide a signature first.")
  } else {
    const dataURL = signaturePad.toDataURL()
    download(dataURL, "signature.png")
  }
})

saveJPGButton.addEventListener("click", () => {
  if (signaturePad.isEmpty()) {
    alert("Please provide a signature first.")
  } else {
    const dataURL = signaturePad.toDataURL("image/jpeg")
    download(dataURL, "signature.jpg")
  }
})

saveSVGButton.addEventListener("click", () => {
  if (signaturePad.isEmpty()) {
    alert("Please provide a signature first.")
  } else {
    const dataURL = signaturePad.toDataURL('image/svg+xml')
    download(dataURL, "signature.svg")
  }
})